home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / ftp / new / ftp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-27  |  31.8 KB  |  1,641 lines

  1. /*
  2.  * Copyright (c) 1985, 1989 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char sccsid[] = "@(#)ftp.c    5.26 (Berkeley) 3/21/89";
  20. #endif /* not lint */
  21.  
  22. #include <sys/param.h>
  23. #include <sys/stat.h>
  24. #include <sys/ioctl.h>
  25. #include <sys/socket.h>
  26. #include <sys/time.h>
  27. #include <sys/file.h>
  28.  
  29. #include <netinet/in.h>
  30. #include <arpa/ftp.h>
  31. #include <arpa/telnet.h>
  32.  
  33. #include <stdio.h>
  34. #include <signal.h>
  35. #include <errno.h>
  36. #include <netdb.h>
  37. #include <fcntl.h>
  38. #include <pwd.h>
  39.  
  40. #include "ftp_var.h"
  41.  
  42. struct    sockaddr_in hisctladdr;
  43. struct    sockaddr_in data_addr;
  44. int    data = -1;
  45. int    abrtflag = 0;
  46. int    ptflag = 0;
  47. int    connected;
  48. struct    sockaddr_in myctladdr;
  49. uid_t    getuid();
  50. off_t    restart_point = 0;
  51.  
  52. FILE    *cin, *cout;
  53. FILE    *dataconn();
  54.  
  55. char *
  56. hookup(host, port)
  57.     char *host;
  58.     int port;
  59. {
  60.     register struct hostent *hp = 0;
  61.     int s,len;
  62.     static char hostnamebuf[80];
  63.  
  64.     bzero((char *)&hisctladdr, sizeof (hisctladdr));
  65.     hisctladdr.sin_addr.s_addr = inet_addr(host);
  66.     if (hisctladdr.sin_addr.s_addr != -1) {
  67.         hisctladdr.sin_family = AF_INET;
  68.         (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
  69.     } else {
  70.         hp = gethostbyname(host);
  71.         if (hp == NULL) {
  72.             fprintf(stderr, "ftp: %s: ", host);
  73.             herror((char *)NULL);
  74.             code = -1;
  75.             return((char *) 0);
  76.         }
  77.         hisctladdr.sin_family = hp->h_addrtype;
  78.         bcopy(hp->h_addr_list[0],
  79.             (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  80.         (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
  81.     }
  82.     hostname = hostnamebuf;
  83.     s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  84.     if (s < 0) {
  85.         perror("ftp: socket");
  86.         code = -1;
  87.         return (0);
  88.     }
  89.     hisctladdr.sin_port = port;
  90.     while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) {
  91.         if (hp && hp->h_addr_list[1]) {
  92.             int oerrno = errno;
  93.  
  94.             fprintf(stderr, "ftp: connect to address %s: ",
  95.                 inet_ntoa(hisctladdr.sin_addr));
  96.             errno = oerrno;
  97.             perror((char *) 0);
  98.             hp->h_addr_list++;
  99.             bcopy(hp->h_addr_list[0],
  100.                  (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  101.             fprintf(stdout, "Trying %s...\n",
  102.                 inet_ntoa(hisctladdr.sin_addr));
  103.             (void) close(s);
  104.             s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  105.             if (s < 0) {
  106.                 perror("ftp: socket");
  107.                 code = -1;
  108.                 return (0);
  109.             }
  110.             continue;
  111.         }
  112.         perror("ftp: connect");
  113.         code = -1;
  114.         goto bad;
  115.     }
  116.     len = sizeof (myctladdr);
  117.     if (getsockname(s, (char *)&myctladdr, &len) < 0) {
  118.         perror("ftp: getsockname");
  119.         code = -1;
  120.         goto bad;
  121.     }
  122.     cin = fdopen(s, "r");
  123.     cout = fdopen(s, "w");
  124.     if (cin == NULL || cout == NULL) {
  125.         fprintf(stderr, "ftp: fdopen failed.\n");
  126.         if (cin)
  127.             (void) fclose(cin);
  128.         if (cout)
  129.             (void) fclose(cout);
  130.         code = -1;
  131.         goto bad;
  132.     }
  133.     if (verbose)
  134.         printf("Connected to %s.\n", hostname);
  135.     if (getreply(0) > 2) {     /* read startup message from server */
  136.         if (cin)
  137.             (void) fclose(cin);
  138.         if (cout)
  139.             (void) fclose(cout);
  140.         code = -1;
  141.         goto bad;
  142.     }
  143. #ifdef SO_OOBINLINE
  144.     {
  145.     int on = 1;
  146.  
  147.     if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))
  148.         < 0 && debug) {
  149.             perror("ftp: setsockopt");
  150.         }
  151.     }
  152. #endif SO_OOBINLINE
  153.  
  154.     return (hostname);
  155. bad:
  156.     (void) close(s);
  157.     return ((char *)0);
  158. }
  159.  
  160. login(host)
  161.     char *host;
  162. {
  163.     char tmp[80];
  164.     char *user, *pass, *acct, *getlogin(), *getpass();
  165.     int n, aflag = 0;
  166.  
  167.     user = pass = acct = 0;
  168.     if (ruserpass(host, &user, &pass, &acct) < 0) {
  169.         code = -1;
  170.         return(0);
  171.     }
  172.     if (user == NULL) {
  173.         char *myname = getlogin();
  174.  
  175.         if (myname == NULL) {
  176.             struct passwd *pp = getpwuid(getuid());
  177.  
  178.             if (pp != NULL)
  179.                 myname = pp->pw_name;
  180.         }
  181.         printf("Name (%s:%s): ", host, myname);
  182.         (void) fgets(tmp, sizeof(tmp) - 1, stdin);
  183.         tmp[strlen(tmp) - 1] = '\0';
  184.         if (*tmp == '\0')
  185.             user = myname;
  186.         else
  187.             user = tmp;
  188.     }
  189.     n = command("USER %s", user);
  190.     if (n == CONTINUE) {
  191.         if (pass == NULL)
  192.             pass = getpass("Password:");
  193.         n = command("PASS %s", pass);
  194.     }
  195.     if (n == CONTINUE) {
  196.         aflag++;
  197.         acct = getpass("Account:");
  198.         n = command("ACCT %s", acct);
  199.     }
  200.     if (n != COMPLETE) {
  201.         fprintf(stderr, "Login failed.\n");
  202.         return (0);
  203.     }
  204.     if (!aflag && acct != NULL)
  205.         (void) command("ACCT %s", acct);
  206.     if (proxy)
  207.         return(1);
  208.     for (n = 0; n < macnum; ++n) {
  209.         if (!strcmp("init", macros[n].mac_name)) {
  210.             (void) strcpy(line, "$init");
  211.             makeargv();
  212.             domacro(margc, margv);
  213.             break;
  214.         }
  215.     }
  216.     return (1);
  217. }
  218.  
  219. cmdabort()
  220. {
  221.     extern jmp_buf ptabort;
  222.  
  223.     printf("\n");
  224.     (void) fflush(stdout);
  225.     abrtflag++;
  226.     if (ptflag)
  227.         longjmp(ptabort,1);
  228. }
  229.  
  230. /*VARARGS1*/
  231. command(fmt, args)
  232.     char *fmt;
  233. {
  234.     int r, (*oldintr)(), cmdabort();
  235.  
  236.     abrtflag = 0;
  237.     if (debug) {
  238.         printf("---> ");
  239.         _doprnt(fmt, &args, stdout);
  240.         printf("\n");
  241.         (void) fflush(stdout);
  242.     }
  243.     if (cout == NULL) {
  244.         perror ("No control connection for command");
  245.         code = -1;
  246.         return (0);
  247.     }
  248.     oldintr = signal(SIGINT,cmdabort);
  249.     _doprnt(fmt, &args, cout);
  250.     fprintf(cout, "\r\n");
  251.     (void) fflush(cout);
  252.     cpend = 1;
  253.     r = getreply(!strcmp(fmt, "QUIT"));
  254.     if (abrtflag && oldintr != SIG_IGN)
  255.         (*oldintr)();
  256.     (void) signal(SIGINT, oldintr);
  257.     return(r);
  258. }
  259.  
  260. char reply_string[BUFSIZ];
  261.  
  262. #include <ctype.h>
  263.  
  264. getreply(expecteof)
  265.     int expecteof;
  266. {
  267.     register int c, n;
  268.     register int dig;
  269.     register char *cp;
  270.     int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort();
  271.     int pflag = 0;
  272.     char *pt = pasv;
  273.  
  274.     cp = reply_string;
  275.     oldintr = signal(SIGINT,cmdabort);
  276.     for (;;) {
  277.         dig = n = code = 0;
  278.         while ((c = getc(cin)) != '\n') {
  279.             if (c == IAC) {     /* handle telnet commands */
  280.                 switch (c = getc(cin)) {
  281.                 case WILL:
  282.                 case WONT:
  283.                     c = getc(cin);
  284.                     fprintf(cout, "%c%c%c",IAC,DONT,c);
  285.                     (void) fflush(cout);
  286.                     break;
  287.                 case DO:
  288.                 case DONT:
  289.                     c = getc(cin);
  290.                     fprintf(cout, "%c%c%c",IAC,WONT,c);
  291.                     (void) fflush(cout);
  292.                     break;
  293.                 default:
  294.                     break;
  295.                 }
  296.                 continue;
  297.             }
  298.             dig++;
  299.             if (c == EOF) {
  300.                 if (expecteof) {
  301.                     (void) signal(SIGINT,oldintr);
  302.                     code = 221;
  303.                     return (0);
  304.                 }
  305.                 lostpeer();
  306.                 if (verbose) {
  307.                     printf("421 Service not available, remote server has closed connection\n");
  308.                     (void) fflush(stdout);
  309.                 }
  310.                 code = 421;
  311.                 return(4);
  312.             }
  313.             if (c != '\r' && (verbose > 0 ||
  314.                 (verbose > -1 && n == '5' && dig > 4))) {
  315.                 if (proxflag &&
  316.                    (dig == 1 || dig == 5 && verbose == 0))
  317.                     printf("%s:",hostname);
  318.                 (void) putchar(c);
  319.             }
  320.             if (dig < 4 && isdigit(c))
  321.                 code = code * 10 + (c - '0');
  322.             if (!pflag && code == 227)
  323.                 pflag = 1;
  324.             if (dig > 4 && pflag == 1 && isdigit(c))
  325.                 pflag = 2;
  326.             if (pflag == 2) {
  327.                 if (c != '\r' && c != ')')
  328.                     *pt++ = c;
  329.                 else {
  330.                     *pt = '\0';
  331.                     pflag = 3;
  332.                 }
  333.             }
  334.             if (dig == 4 && c == '-') {
  335.                 if (continuation)
  336.                     code = 0;
  337.                 continuation++;
  338.             }
  339.             if (n == 0)
  340.                 n = c;
  341.             *cp++ = c;
  342.         }
  343.         if (verbose > 0 || verbose > -1 && n == '5') {
  344.             (void) putchar(c);
  345.             (void) fflush (stdout);
  346.         }
  347.         if (continuation && code != originalcode) {
  348.             if (originalcode == 0)
  349.                 originalcode = code;
  350.             continue;
  351.         }
  352.         *cp = '\0';
  353.         if (n != '1')
  354.             cpend = 0;
  355.         (void) signal(SIGINT,oldintr);
  356.         if (code == 421 || originalcode == 421)
  357.             lostpeer();
  358.         if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
  359.             (*oldintr)();
  360.         return (n - '0');
  361.     }
  362. }
  363.  
  364. empty(mask, sec)
  365.     struct fd_set *mask;
  366.     int sec;
  367. {
  368.     struct timeval t;
  369.  
  370.     t.tv_sec = (long) sec;
  371.     t.tv_usec = 0;
  372.     return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
  373. }
  374.  
  375. jmp_buf    sendabort;
  376.  
  377. abortsend()
  378. {
  379.  
  380.     mflag = 0;
  381.     abrtflag = 0;
  382.     printf("\nsend aborted\n");
  383.     (void) fflush(stdout);
  384.     longjmp(sendabort, 1);
  385. }
  386.  
  387. #define HASHBYTES 1024
  388.  
  389. sendrequest(cmd, local, remote, printnames)
  390.     char *cmd, *local, *remote;
  391.     int printnames;
  392. {
  393.     FILE *fin, *dout = 0, *popen();
  394.     int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)();
  395.     int abortsend();
  396.     char buf[BUFSIZ], *bufp;
  397.     long bytes = 0, hashbytes = HASHBYTES;
  398.     register int c, d;
  399.     struct stat st;
  400.     struct timeval start, stop;
  401.     char *mode;
  402.  
  403.     if (verbose && printnames) {
  404.         if (local && *local != '-')
  405.             printf("local: %s ", local);
  406.         if (remote)
  407.             printf("remote: %s\n", remote);
  408.     }
  409.     if (proxy) {
  410.         proxtrans(cmd, local, remote);
  411.         return;
  412.     }
  413.     closefunc = NULL;
  414.     oldintr = NULL;
  415.     oldintp = NULL;
  416.     mode = "w";
  417.     if (setjmp(sendabort)) {
  418.         while (cpend) {
  419.             (void) getreply(0);
  420.         }
  421.         if (data >= 0) {
  422.             (void) close(data);
  423.             data = -1;
  424.         }
  425.         if (oldintr)
  426.             (void) signal(SIGINT,oldintr);
  427.         if (oldintp)
  428.             (void) signal(SIGPIPE,oldintp);
  429.         code = -1;
  430.         return;
  431.     }
  432.     oldintr = signal(SIGINT, abortsend);
  433.     if (strcmp(local, "-") == 0)
  434.         fin = stdin;
  435.     else if (*local == '|') {
  436.         oldintp = signal(SIGPIPE,SIG_IGN);
  437.         fin = popen(local + 1, "r");
  438.         if (fin == NULL) {
  439.             perror(local + 1);
  440.             (void) signal(SIGINT, oldintr);
  441.             (void) signal(SIGPIPE, oldintp);
  442.             code = -1;
  443.             return;
  444.         }
  445.         closefunc = pclose;
  446.     } else {
  447.         fin = fopen(local, "r");
  448.         if (fin == NULL) {
  449.             perror(local);
  450.             (void) signal(SIGINT, oldintr);
  451.             code = -1;
  452.             return;
  453.         }
  454.         closefunc = fclose;
  455.         if (fstat(fileno(fin), &st) < 0 ||
  456.             (st.st_mode&S_IFMT) != S_IFREG) {
  457.             fprintf(stdout, "%s: not a plain file.\n", local);
  458.             (void) signal(SIGINT, oldintr);
  459.             fclose(fin);
  460.             code = -1;
  461.             return;
  462.         }
  463.     }
  464.     if (initconn()) {
  465.         (void) signal(SIGINT, oldintr);
  466.         if (oldintp)
  467.             (void) signal(SIGPIPE, oldintp);
  468.         code = -1;
  469.         if (closefunc != NULL)
  470.             (*closefunc)(fin);
  471.         return;
  472.     }
  473.     if (setjmp(sendabort))
  474.         goto abort;
  475.  
  476.     if (restart_point &&
  477.         (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
  478.         if (fseek(fin, (long) restart_point, 0) < 0) {
  479.             perror(local);
  480.             restart_point = 0;
  481.             if (closefunc != NULL)
  482.                 (*closefunc)(fin);
  483.             return;
  484.         }
  485.         if (command("REST %ld", (long) restart_point)
  486.             != CONTINUE) {
  487.             restart_point = 0;
  488.             if (closefunc != NULL)
  489.                 (*closefunc)(fin);
  490.             return;
  491.         }
  492.         restart_point = 0;
  493.         mode = "r+w";
  494.     }
  495.     if (remote) {
  496.         if (command("%s %s", cmd, remote) != PRELIM) {
  497.             (void) signal(SIGINT, oldintr);
  498.             if (oldintp)
  499.                 (void) signal(SIGPIPE, oldintp);
  500.             if (closefunc != NULL)
  501.                 (*closefunc)(fin);
  502.             return;
  503.         }
  504.     } else
  505.         if (command("%s", cmd) != PRELIM) {
  506.             (void) signal(SIGINT, oldintr);
  507.             if (oldintp)
  508.                 (void) signal(SIGPIPE, oldintp);
  509.             if (closefunc != NULL)
  510.                 (*closefunc)(fin);
  511.             return;
  512.         }
  513.     dout = dataconn(mode);
  514.     if (dout == NULL)
  515.         goto abort;
  516.     (void) gettimeofday(&start, (struct timezone *)0);
  517.     oldintp = signal(SIGPIPE, SIG_IGN);
  518.     switch (type) {
  519.  
  520.     case TYPE_I:
  521.     case TYPE_L:
  522.         errno = d = 0;
  523.         while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
  524.             bytes += c;
  525.             for (bufp = buf; c > 0; c -= d, bufp += d)
  526.                 if ((d = write(fileno(dout), bufp, c)) <= 0)
  527.                     break;
  528.             if (hash) {
  529.                 while (bytes >= hashbytes) {
  530.                     (void) putchar('#');
  531.                     hashbytes += HASHBYTES;
  532.                 }
  533.                 (void) fflush(stdout);
  534.             }
  535.         }
  536.         if (hash && bytes > 0) {
  537.             if (bytes < HASHBYTES)
  538.                 (void) putchar('#');
  539.             (void) putchar('\n');
  540.             (void) fflush(stdout);
  541.         }
  542.         if (c < 0)
  543.             perror(local);
  544.         if (d <= 0) {
  545.             if (d == 0)
  546.                 fprintf(stderr, "netout: write returned 0?\n");
  547.             else if (errno != EPIPE) 
  548.                 perror("netout");
  549.             bytes = -1;
  550.         }
  551.         break;
  552.  
  553.     case TYPE_A:
  554.         while ((c = getc(fin)) != EOF) {
  555.             if (c == '\n') {
  556.                 while (hash && (bytes >= hashbytes)) {
  557.                     (void) putchar('#');
  558.                     (void) fflush(stdout);
  559.                     hashbytes += HASHBYTES;
  560.                 }
  561.                 if (ferror(dout))
  562.                     break;
  563.                 (void) putc('\r', dout);
  564.                 bytes++;
  565.             }
  566.             (void) putc(c, dout);
  567.             bytes++;
  568.     /*        if (c == '\r') {                  */
  569.     /*        (void)    putc('\0', dout);  /* this violates rfc */
  570.     /*            bytes++;                */
  571.     /*        }                                      */    
  572.         }
  573.         if (hash) {
  574.             if (bytes < hashbytes)
  575.                 (void) putchar('#');
  576.             (void) putchar('\n');
  577.             (void) fflush(stdout);
  578.         }
  579.         if (ferror(fin))
  580.             perror(local);
  581.         if (ferror(dout)) {
  582.             if (errno != EPIPE)
  583.                 perror("netout");
  584.             bytes = -1;
  585.         }
  586.         break;
  587.     }
  588.     (void) gettimeofday(&stop, (struct timezone *)0);
  589.     if (closefunc != NULL)
  590.         (*closefunc)(fin);
  591.     (void) fclose(dout);
  592.     (void) getreply(0);
  593.     (void) signal(SIGINT, oldintr);
  594.     if (oldintp)
  595.         (void) signal(SIGPIPE, oldintp);
  596.     if (bytes > 0)
  597.         ptransfer("sent", bytes, &start, &stop);
  598.     return;
  599. abort:
  600.     (void) gettimeofday(&stop, (struct timezone *)0);
  601.     (void) signal(SIGINT, oldintr);
  602.     if (oldintp)
  603.         (void) signal(SIGPIPE, oldintp);
  604.     if (!cpend) {
  605.         code = -1;
  606.         return;
  607.     }
  608.     if (data >= 0) {
  609.         (void) close(data);
  610.         data = -1;
  611.     }
  612.     if (dout)
  613.         (void) fclose(dout);
  614.     (void) getreply(0);
  615.     code = -1;
  616.     if (closefunc != NULL && fin != NULL)
  617.         (*closefunc)(fin);
  618.     if (bytes > 0)
  619.         ptransfer("sent", bytes, &start, &stop);
  620. }
  621.  
  622. jmp_buf    recvabort;
  623.  
  624. abortrecv()
  625. {
  626.  
  627.     mflag = 0;
  628.     abrtflag = 0;
  629.     printf("\n");
  630.     (void) fflush(stdout);
  631.     longjmp(recvabort, 1);
  632. }
  633.  
  634. recvrequest(cmd, local, remote, mode, printnames)
  635.     char *cmd, *local, *remote, *mode;
  636. {
  637.     FILE *fout, *din = 0, *popen();
  638.     int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 
  639.     int abortrecv(), oldverbose, oldtype = 0, is_retr, tcrflag, nfnd;
  640.     char *bufp, *gunique(), msg;
  641.     static char *buf;
  642.     static int bufsize;
  643.     long bytes = 0, hashbytes = HASHBYTES;
  644.     struct fd_set mask;
  645.     register int c, d;
  646.     struct timeval start, stop;
  647.     struct stat st;
  648.     extern char *malloc();
  649.  
  650.     is_retr = strcmp(cmd, "RETR") == 0;
  651.     if (is_retr && verbose && printnames) {
  652.         if (local && *local != '-')
  653.             printf("local: %s ", local);
  654.         if (remote)
  655.             printf("remote: %s\n", remote);
  656.     }
  657.     if (proxy && is_retr) {
  658.         proxtrans(cmd, local, remote);
  659.         return;
  660.     }
  661.     closefunc = NULL;
  662.     oldintr = NULL;
  663.     oldintp = NULL;
  664.     tcrflag = !crflag && is_retr;
  665.     if (setjmp(recvabort)) {
  666.         while (cpend) {
  667.             (void) getreply(0);
  668.         }
  669.         if (data >= 0) {
  670.             (void) close(data);
  671.             data = -1;
  672.         }
  673.         if (oldintr)
  674.             (void) signal(SIGINT, oldintr);
  675.         code = -1;
  676.         return;
  677.     }
  678.     oldintr = signal(SIGINT, abortrecv);
  679.     if (strcmp(local, "-") && *local != '|') {
  680.         if (access(local, 2) < 0) {
  681.             char *dir = rindex(local, '/');
  682.  
  683.             if (errno != ENOENT && errno != EACCES) {
  684.                 perror(local);
  685.                 (void) signal(SIGINT, oldintr);
  686.                 code = -1;
  687.                 return;
  688.             }
  689.             if (dir != NULL)
  690.                 *dir = 0;
  691.             d = access(dir ? local : ".", 2);
  692.             if (dir != NULL)
  693.                 *dir = '/';
  694.             if (d < 0) {
  695.                 perror(local);
  696.                 (void) signal(SIGINT, oldintr);
  697.                 code = -1;
  698.                 return;
  699.             }
  700.             if (!runique && errno == EACCES &&
  701.                 chmod(local, 0600) < 0) {
  702.                 perror(local);
  703.                 (void) signal(SIGINT, oldintr);
  704.                 code = -1;
  705.                 return;
  706.             }
  707.             if (runique && errno == EACCES &&
  708.                (local = gunique(local)) == NULL) {
  709.                 (void) signal(SIGINT, oldintr);
  710.                 code = -1;
  711.                 return;
  712.             }
  713.         }
  714.         else if (runique && (local = gunique(local)) == NULL) {
  715.             (void) signal(SIGINT, oldintr);
  716.             code = -1;
  717.             return;
  718.         }
  719.     }
  720.     if (initconn()) {
  721.         (void) signal(SIGINT, oldintr);
  722.         code = -1;
  723.         return;
  724.     }
  725.     if (setjmp(recvabort))
  726.         goto abort;
  727.     if (!is_retr) {
  728.         if (type != TYPE_A) {
  729.             oldtype = type;
  730.             oldverbose = verbose;
  731.             if (!debug)
  732.                 verbose = 0;
  733.             setascii();
  734.             verbose = oldverbose;
  735.         }
  736.     } else if (restart_point) {
  737.         if (command("REST %ld", (long) restart_point) != CONTINUE)
  738.             return;
  739.     }
  740.     if (remote) {
  741.         if (command("%s %s", cmd, remote) != PRELIM) {
  742.             (void) signal(SIGINT, oldintr);
  743.             if (oldtype) {
  744.                 if (!debug)
  745.                     verbose = 0;
  746.                 switch (oldtype) {
  747.                     case TYPE_I:
  748.                         setbinary();
  749.                         break;
  750.                     case TYPE_E:
  751.                         setebcdic();
  752.                         break;
  753.                     case TYPE_L:
  754.                         settenex();
  755.                         break;
  756.                 }
  757.                 verbose = oldverbose;
  758.             }
  759.             return;
  760.         }
  761.     } else {
  762.         if (command("%s", cmd) != PRELIM) {
  763.             (void) signal(SIGINT, oldintr);
  764.             if (oldtype) {
  765.                 if (!debug)
  766.                     verbose = 0;
  767.                 switch (oldtype) {
  768.                     case TYPE_I:
  769.                         setbinary();
  770.                         break;
  771.                     case TYPE_E:
  772.                         setebcdic();
  773.                         break;
  774.                     case TYPE_L:
  775.                         settenex();
  776.                         break;
  777.                 }
  778.                 verbose = oldverbose;
  779.             }
  780.             return;
  781.         }
  782.     }
  783.     din = dataconn("r");
  784.     if (din == NULL)
  785.         goto abort;
  786.     if (strcmp(local, "-") == 0)
  787.         fout = stdout;
  788.     else if (*local == '|') {
  789.         oldintp = signal(SIGPIPE, SIG_IGN);
  790.         fout = popen(local + 1, "w");
  791.         if (fout == NULL) {
  792.             perror(local+1);
  793.             goto abort;
  794.         }
  795.         closefunc = pclose;
  796.     } else {
  797.         fout = fopen(local, mode);
  798.         if (fout == NULL) {
  799.             perror(local);
  800.             goto abort;
  801.         }
  802.         closefunc = fclose;
  803.     }
  804.     if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
  805.         st.st_blksize = BUFSIZ;
  806.     if (st.st_blksize > bufsize) {
  807.         if (buf)
  808.             (void) free(buf);
  809.         buf = malloc(st.st_blksize);
  810.         if (buf == NULL) {
  811.             perror("malloc");
  812.             bufsize = 0;
  813.             goto abort;
  814.         }
  815.         bufsize = st.st_blksize;
  816.     }
  817.     (void) gettimeofday(&start, (struct timezone *)0);
  818.     switch (type) {
  819.  
  820.     case TYPE_I:
  821.     case TYPE_L:
  822.         if (restart_point &&
  823.             lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
  824.             perror(local);
  825.             if (closefunc != NULL)
  826.                 (*closefunc)(fout);
  827.             return;
  828.         }
  829.         errno = d = 0;
  830.         while ((c = read(fileno(din), buf, bufsize)) > 0) {
  831.             if ((d = write(fileno(fout), buf, c)) != c)
  832.                 break;
  833.             bytes += c;
  834.             if (hash) {
  835.                 while (bytes >= hashbytes) {
  836.                     (void) putchar('#');
  837.                     hashbytes += HASHBYTES;
  838.                 }
  839.                 (void) fflush(stdout);
  840.             }
  841.         }
  842.         if (hash && bytes > 0) {
  843.             if (bytes < HASHBYTES)
  844.                 (void) putchar('#');
  845.             (void) putchar('\n');
  846.             (void) fflush(stdout);
  847.         }
  848.         if (c < 0) {
  849.             if (errno != EPIPE)
  850.                 perror("netin");
  851.             bytes = -1;
  852.         }
  853.         if (d < c) {
  854.             if (d < 0)
  855.                 perror(local);
  856.             else
  857.                 fprintf(stderr, "%s: short write\n", local);
  858.         }
  859.         break;
  860.  
  861.     case TYPE_A:
  862.         if (restart_point) {
  863.             register int i, n, c;
  864.  
  865.             if (fseek(fout, 0L, L_SET) < 0)
  866.                 goto done;
  867.             n = restart_point;
  868.             i = 0;
  869.             while (i++ < n) {
  870.                 if ((c=getc(fout)) == EOF)
  871.                     goto done;
  872.                 if (c == '\n')
  873.                     i++;
  874.             }
  875.             if (fseek(fout, 0L, L_INCR) < 0) {
  876. done:
  877.                 perror(local);
  878.                 if (closefunc != NULL)
  879.                     (*closefunc)(fout);
  880.                 return;
  881.             }
  882.         }
  883.         while ((c = getc(din)) != EOF) {
  884.             while (c == '\r') {
  885.                 while (hash && (bytes >= hashbytes)) {
  886.                     (void) putchar('#');
  887.                     (void) fflush(stdout);
  888.                     hashbytes += HASHBYTES;
  889.                 }
  890.                 bytes++;
  891.                 if ((c = getc(din)) != '\n' || tcrflag) {
  892.                     if (ferror(fout))
  893.                         goto break2;
  894.                     (void) putc('\r', fout);
  895.                     if (c == '\0') {
  896.                         bytes++;
  897.                         goto contin2;
  898.                     }
  899.                     if (c == EOF)
  900.                         goto contin2;
  901.                 }
  902.             }
  903.             (void) putc(c, fout);
  904.             bytes++;
  905.     contin2:    ;
  906.         }
  907. break2:
  908.         if (hash) {
  909.             if (bytes < hashbytes)
  910.                 (void) putchar('#');
  911.             (void) putchar('\n');
  912.             (void) fflush(stdout);
  913.         }
  914.         if (ferror(din)) {
  915.             if (errno != EPIPE)
  916.                 perror("netin");
  917.             bytes = -1;
  918.         }
  919.         if (ferror(fout))
  920.             perror(local);
  921.         break;
  922.     }
  923.     if (closefunc != NULL)
  924.         (*closefunc)(fout);
  925.     (void) signal(SIGINT, oldintr);
  926.     if (oldintp)
  927.         (void) signal(SIGPIPE, oldintp);
  928.     (void) gettimeofday(&stop, (struct timezone *)0);
  929.     (void) fclose(din);
  930.     (void) getreply(0);
  931.     if (bytes > 0 && is_retr)
  932.         ptransfer("received", bytes, &start, &stop);
  933.     if (oldtype) {
  934.         if (!debug)
  935.             verbose = 0;
  936.         switch (oldtype) {
  937.             case TYPE_I:
  938.                 setbinary();
  939.                 break;
  940.             case TYPE_E:
  941.                 setebcdic();
  942.                 break;
  943.             case TYPE_L:
  944.                 settenex();
  945.                 break;
  946.         }
  947.         verbose = oldverbose;
  948.     }
  949.     return;
  950. abort:
  951.  
  952. /* abort using RFC959 recommended IP,SYNC sequence  */
  953.  
  954.     (void) gettimeofday(&stop, (struct timezone *)0);
  955.     if (oldintp)
  956.         (void) signal(SIGPIPE, oldintr);
  957.     (void) signal(SIGINT,SIG_IGN);
  958.     if (oldtype) {
  959.         if (!debug)
  960.             verbose = 0;
  961.         switch (oldtype) {
  962.             case TYPE_I:
  963.                 setbinary();
  964.                 break;
  965.             case TYPE_E:
  966.                 setebcdic();
  967.                 break;
  968.             case TYPE_L:
  969.                 settenex();
  970.                 break;
  971.         }
  972.         verbose = oldverbose;
  973.     }
  974.     if (!cpend) {
  975.         code = -1;
  976.         (void) signal(SIGINT,oldintr);
  977.         return;
  978.     }
  979.  
  980.     fprintf(cout,"%c%c",IAC,IP);
  981.     (void) fflush(cout); 
  982.     msg = IAC;
  983. /* send IAC in urgent mode instead of DM because UNIX places oob mark */
  984. /* after urgent byte rather than before as now is protocol            */
  985.     if (send(fileno(cout),&msg,1,MSG_OOB) != 1) {
  986.         perror("abort");
  987.     }
  988.     fprintf(cout,"%cABOR\r\n",DM);
  989.     (void) fflush(cout);
  990.     FD_ZERO(&mask);
  991.     FD_SET(fileno(cin), &mask);
  992.     if (din) { 
  993.         FD_SET(fileno(din), &mask);
  994.     }
  995.     if ((nfnd = empty(&mask,10)) <= 0) {
  996.         if (nfnd < 0) {
  997.             perror("abort");
  998.         }
  999.         code = -1;
  1000.         lostpeer();
  1001.     }
  1002.     if (din && FD_ISSET(fileno(din), &mask)) {
  1003.         while ((c = read(fileno(din), buf, bufsize)) > 0)
  1004.             ;
  1005.     }
  1006.     if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */
  1007.         if (data >= 0) {
  1008.             (void) close(data);
  1009.             data = -1;
  1010.         }
  1011.         (void) getreply(0);
  1012.     }
  1013.     (void) getreply(0);
  1014.     code = -1;
  1015.     if (data >= 0) {
  1016.         (void) close(data);
  1017.         data = -1;
  1018.     }
  1019.     if (closefunc != NULL && fout != NULL)
  1020.         (*closefunc)(fout);
  1021.     if (din)
  1022.         (void) fclose(din);
  1023.     if (bytes > 0)
  1024.         ptransfer("received", bytes, &start, &stop);
  1025.     (void) signal(SIGINT,oldintr);
  1026. }
  1027.  
  1028. /*
  1029.  * Need to start a listen on the data channel
  1030.  * before we send the command, otherwise the
  1031.  * server's connect may fail.
  1032.  */
  1033. int sendport = -1;
  1034.  
  1035. initconn()
  1036. {
  1037.     register char *p, *a;
  1038.     int result, len, tmpno = 0;
  1039.     int on = 1;
  1040.  
  1041. noport:
  1042.     data_addr = myctladdr;
  1043.     if (sendport)
  1044.         data_addr.sin_port = 0;    /* let system pick one */ 
  1045.     if (data != -1)
  1046.         (void) close (data);
  1047.     data = socket(AF_INET, SOCK_STREAM, 0);
  1048.     if (data < 0) {
  1049.         perror("ftp: socket");
  1050.         if (tmpno)
  1051.             sendport = 1;
  1052.         return (1);
  1053.     }
  1054.     if (!sendport)
  1055.         if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
  1056.             perror("ftp: setsockopt (reuse address)");
  1057.             goto bad;
  1058.         }
  1059.     if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
  1060.         perror("ftp: bind");
  1061.         goto bad;
  1062.     }
  1063.     if (options & SO_DEBUG &&
  1064.         setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
  1065.         perror("ftp: setsockopt (ignored)");
  1066.     len = sizeof (data_addr);
  1067.     if (getsockname(data, (char *)&data_addr, &len) < 0) {
  1068.         perror("ftp: getsockname");
  1069.         goto bad;
  1070.     }
  1071.     if (listen(data, 1) < 0)
  1072.         perror("ftp: listen");
  1073.     if (sendport) {
  1074.         a = (char *)&data_addr.sin_addr;
  1075.         p = (char *)&data_addr.sin_port;
  1076. #define    UC(b)    (((int)b)&0xff)
  1077.         result =
  1078.             command("PORT %d,%d,%d,%d,%d,%d",
  1079.               UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
  1080.               UC(p[0]), UC(p[1]));
  1081.         if (result == ERROR && sendport == -1) {
  1082.             sendport = 0;
  1083.             tmpno = 1;
  1084.             goto noport;
  1085.         }
  1086.         return (result != COMPLETE);
  1087.     }
  1088.     if (tmpno)
  1089.         sendport = 1;
  1090.     return (0);
  1091. bad:
  1092.     (void) close(data), data = -1;
  1093.     if (tmpno)
  1094.         sendport = 1;
  1095.     return (1);
  1096. }
  1097.  
  1098. FILE *
  1099. dataconn(mode)
  1100.     char *mode;
  1101. {
  1102.     struct sockaddr_in from;
  1103.     int s, fromlen = sizeof (from);
  1104.  
  1105.     s = accept(data, (struct sockaddr *) &from, &fromlen);
  1106.     if (s < 0) {
  1107.         perror("ftp: accept");
  1108.         (void) close(data), data = -1;
  1109.         return (NULL);
  1110.     }
  1111.     (void) close(data);
  1112.     data = s;
  1113.     return (fdopen(data, mode));
  1114. }
  1115.  
  1116. ptransfer(direction, bytes, t0, t1)
  1117.     char *direction;
  1118.     long bytes;
  1119.     struct timeval *t0, *t1;
  1120. {
  1121.     struct timeval td;
  1122.     float s, bs;
  1123.  
  1124.     if (verbose) {
  1125.         tvsub(&td, t1, t0);
  1126.         s = td.tv_sec + (td.tv_usec / 1000000.);
  1127. #define    nz(x)    ((x) == 0 ? 1 : (x))
  1128.         bs = bytes / nz(s);
  1129.         printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
  1130.             bytes, direction, s, bs / 1024.);
  1131.     }
  1132. }
  1133.  
  1134. /*tvadd(tsum, t0)
  1135.     struct timeval *tsum, *t0;
  1136. {
  1137.  
  1138.     tsum->tv_sec += t0->tv_sec;
  1139.     tsum->tv_usec += t0->tv_usec;
  1140.     if (tsum->tv_usec > 1000000)
  1141.         tsum->tv_sec++, tsum->tv_usec -= 1000000;
  1142. } */
  1143.  
  1144. tvsub(tdiff, t1, t0)
  1145.     struct timeval *tdiff, *t1, *t0;
  1146. {
  1147.  
  1148.     tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
  1149.     tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
  1150.     if (tdiff->tv_usec < 0)
  1151.         tdiff->tv_sec--, tdiff->tv_usec += 1000000;
  1152. }
  1153.  
  1154. psabort()
  1155. {
  1156.     extern int abrtflag;
  1157.  
  1158.     abrtflag++;
  1159. }
  1160.  
  1161. pswitch(flag)
  1162.     int flag;
  1163. {
  1164.     extern int proxy, abrtflag;
  1165.     int (*oldintr)();
  1166.     static struct comvars {
  1167.         int connect;
  1168.         char name[MAXHOSTNAMELEN];
  1169.         struct sockaddr_in mctl;
  1170.         struct sockaddr_in hctl;
  1171.         FILE *in;
  1172.         FILE *out;
  1173.         int tpe;
  1174.         int cpnd;
  1175.         int sunqe;
  1176.         int runqe;
  1177.         int mcse;
  1178.         int ntflg;
  1179.         char nti[17];
  1180.         char nto[17];
  1181.         int mapflg;
  1182.         char mi[MAXPATHLEN];
  1183.         char mo[MAXPATHLEN];
  1184.         } proxstruct, tmpstruct;
  1185.     struct comvars *ip, *op;
  1186.  
  1187.     abrtflag = 0;
  1188.     oldintr = signal(SIGINT, psabort);
  1189.     if (flag) {
  1190.         if (proxy)
  1191.             return;
  1192.         ip = &tmpstruct;
  1193.         op = &proxstruct;
  1194.         proxy++;
  1195.     }
  1196.     else {
  1197.         if (!proxy)
  1198.             return;
  1199.         ip = &proxstruct;
  1200.         op = &tmpstruct;
  1201.         proxy = 0;
  1202.     }
  1203.     ip->connect = connected;
  1204.     connected = op->connect;
  1205.     if (hostname) {
  1206.         (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
  1207.         ip->name[strlen(ip->name)] = '\0';
  1208.     } else
  1209.         ip->name[0] = 0;
  1210.     hostname = op->name;
  1211.     ip->hctl = hisctladdr;
  1212.     hisctladdr = op->hctl;
  1213.     ip->mctl = myctladdr;
  1214.     myctladdr = op->mctl;
  1215.     ip->in = cin;
  1216.     cin = op->in;
  1217.     ip->out = cout;
  1218.     cout = op->out;
  1219.     ip->tpe = type;
  1220.     type = op->tpe;
  1221.     if (!type)
  1222.         type = 1;
  1223.     ip->cpnd = cpend;
  1224.     cpend = op->cpnd;
  1225.     ip->sunqe = sunique;
  1226.     sunique = op->sunqe;
  1227.     ip->runqe = runique;
  1228.     runique = op->runqe;
  1229.     ip->mcse = mcase;
  1230.     mcase = op->mcse;
  1231.     ip->ntflg = ntflag;
  1232.     ntflag = op->ntflg;
  1233.     (void) strncpy(ip->nti, ntin, 16);
  1234.     (ip->nti)[strlen(ip->nti)] = '\0';
  1235.     (void) strcpy(ntin, op->nti);
  1236.     (void) strncpy(ip->nto, ntout, 16);
  1237.     (ip->nto)[strlen(ip->nto)] = '\0';
  1238.     (void) strcpy(ntout, op->nto);
  1239.     ip->mapflg = mapflag;
  1240.     mapflag = op->mapflg;
  1241.     (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
  1242.     (ip->mi)[strlen(ip->mi)] = '\0';
  1243.     (void) strcpy(mapin, op->mi);
  1244.     (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
  1245.     (ip->mo)[strlen(ip->mo)] = '\0';
  1246.     (void) strcpy(mapout, op->mo);
  1247.     (void) signal(SIGINT, oldintr);
  1248.     if (abrtflag) {
  1249.         abrtflag = 0;
  1250.         (*oldintr)();
  1251.     }
  1252. }
  1253.  
  1254. jmp_buf ptabort;
  1255. int ptabflg;
  1256.  
  1257. abortpt()
  1258. {
  1259.     printf("\n");
  1260.     (void) fflush(stdout);
  1261.     ptabflg++;
  1262.     mflag = 0;
  1263.     abrtflag = 0;
  1264.     longjmp(ptabort, 1);
  1265. }
  1266.  
  1267. proxtrans(cmd, local, remote)
  1268.     char *cmd, *local, *remote;
  1269. {
  1270.     int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd;
  1271.     extern jmp_buf ptabort;
  1272.     char *cmd2;
  1273.     struct fd_set mask;
  1274.  
  1275.     if (strcmp(cmd, "RETR"))
  1276.         cmd2 = "RETR";
  1277.     else
  1278.         cmd2 = runique ? "STOU" : "STOR";
  1279.     if (command("PASV") != COMPLETE) {
  1280.         printf("proxy server does not support third part transfers.\n");
  1281.         return;
  1282.     }
  1283.     tmptype = type;
  1284.     pswitch(0);
  1285.     if (!connected) {
  1286.         printf("No primary connection\n");
  1287.         pswitch(1);
  1288.         code = -1;
  1289.         return;
  1290.     }
  1291.     if (type != tmptype) {
  1292.         oldtype = type;
  1293.         switch (tmptype) {
  1294.             case TYPE_A:
  1295.                 setascii();
  1296.                 break;
  1297.             case TYPE_I:
  1298.                 setbinary();
  1299.                 break;
  1300.             case TYPE_E:
  1301.                 setebcdic();
  1302.                 break;
  1303.             case TYPE_L:
  1304.                 settenex();
  1305.                 break;
  1306.         }
  1307.     }
  1308.     if (command("PORT %s", pasv) != COMPLETE) {
  1309.         switch (oldtype) {
  1310.             case 0:
  1311.                 break;
  1312.             case TYPE_A:
  1313.                 setascii();
  1314.                 break;
  1315.             case TYPE_I:
  1316.                 setbinary();
  1317.                 break;
  1318.             case TYPE_E:
  1319.                 setebcdic();
  1320.                 break;
  1321.             case TYPE_L:
  1322.                 settenex();
  1323.                 break;
  1324.         }
  1325.         pswitch(1);
  1326.         return;
  1327.     }
  1328.     if (setjmp(ptabort))
  1329.         goto abort;
  1330.     oldintr = signal(SIGINT, abortpt);
  1331.     if (command("%s %s", cmd, remote) != PRELIM) {
  1332.         (void) signal(SIGINT, oldintr);
  1333.         switch (oldtype) {
  1334.             case 0:
  1335.                 break;
  1336.             case TYPE_A:
  1337.                 setascii();
  1338.                 break;
  1339.             case TYPE_I:
  1340.                 setbinary();
  1341.                 break;
  1342.             case TYPE_E:
  1343.                 setebcdic();
  1344.                 break;
  1345.             case TYPE_L:
  1346.                 settenex();
  1347.                 break;
  1348.         }
  1349.         pswitch(1);
  1350.         return;
  1351.     }
  1352.     sleep(2);
  1353.     pswitch(1);
  1354.     secndflag++;
  1355.     if (command("%s %s", cmd2, local) != PRELIM)
  1356.         goto abort;
  1357.     ptflag++;
  1358.     (void) getreply(0);
  1359.     pswitch(0);
  1360.     (void) getreply(0);
  1361.     (void) signal(SIGINT, oldintr);
  1362.     switch (oldtype) {
  1363.         case 0:
  1364.             break;
  1365.         case TYPE_A:
  1366.             setascii();
  1367.             break;
  1368.         case TYPE_I:
  1369.             setbinary();
  1370.             break;
  1371.         case TYPE_E:
  1372.             setebcdic();
  1373.             break;
  1374.         case TYPE_L:
  1375.             settenex();
  1376.             break;
  1377.     }
  1378.     pswitch(1);
  1379.     ptflag = 0;
  1380.     printf("local: %s remote: %s\n", local, remote);
  1381.     return;
  1382. abort:
  1383.     (void) signal(SIGINT, SIG_IGN);
  1384.     ptflag = 0;
  1385.     if (strcmp(cmd, "RETR") && !proxy)
  1386.         pswitch(1);
  1387.     else if (!strcmp(cmd, "RETR") && proxy)
  1388.         pswitch(0);
  1389.     if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
  1390.         if (command("%s %s", cmd2, local) != PRELIM) {
  1391.             pswitch(0);
  1392.             switch (oldtype) {
  1393.                 case 0:
  1394.                     break;
  1395.                 case TYPE_A:
  1396.                     setascii();
  1397.                     break;
  1398.                 case TYPE_I:
  1399.                     setbinary();
  1400.                     break;
  1401.                 case TYPE_E:
  1402.                     setebcdic();
  1403.                     break;
  1404.                 case TYPE_L:
  1405.                     settenex();
  1406.                     break;
  1407.             }
  1408.             if (cpend) {
  1409.                 char msg[2];
  1410.  
  1411.                 fprintf(cout,"%c%c",IAC,IP);
  1412.                 (void) fflush(cout); 
  1413.                 *msg = IAC;
  1414.                 *(msg+1) = DM;
  1415.                 if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1416.                     perror("abort");
  1417.                 fprintf(cout,"ABOR\r\n");
  1418.                 (void) fflush(cout);
  1419.                 FD_ZERO(&mask);
  1420.                 FD_SET(fileno(cin), &mask);
  1421.                 if ((nfnd = empty(&mask,10)) <= 0) {
  1422.                     if (nfnd < 0) {
  1423.                         perror("abort");
  1424.                     }
  1425.                     if (ptabflg)
  1426.                         code = -1;
  1427.                     lostpeer();
  1428.                 }
  1429.                 (void) getreply(0);
  1430.                 (void) getreply(0);
  1431.             }
  1432.         }
  1433.         pswitch(1);
  1434.         if (ptabflg)
  1435.             code = -1;
  1436.         (void) signal(SIGINT, oldintr);
  1437.         return;
  1438.     }
  1439.     if (cpend) {
  1440.         char msg[2];
  1441.  
  1442.         fprintf(cout,"%c%c",IAC,IP);
  1443.         (void) fflush(cout); 
  1444.         *msg = IAC;
  1445.         *(msg+1) = DM;
  1446.         if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1447.             perror("abort");
  1448.         fprintf(cout,"ABOR\r\n");
  1449.         (void) fflush(cout);
  1450.         FD_ZERO(&mask);
  1451.         FD_SET(fileno(cin), &mask);
  1452.         if ((nfnd = empty(&mask,10)) <= 0) {
  1453.             if (nfnd < 0) {
  1454.                 perror("abort");
  1455.             }
  1456.             if (ptabflg)
  1457.                 code = -1;
  1458.             lostpeer();
  1459.         }
  1460.         (void) getreply(0);
  1461.         (void) getreply(0);
  1462.     }
  1463.     pswitch(!proxy);
  1464.     if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
  1465.         if (command("%s %s", cmd2, local) != PRELIM) {
  1466.             pswitch(0);
  1467.             switch (oldtype) {
  1468.                 case 0:
  1469.                     break;
  1470.                 case TYPE_A:
  1471.                     setascii();
  1472.                     break;
  1473.                 case TYPE_I:
  1474.                     setbinary();
  1475.                     break;
  1476.                 case TYPE_E:
  1477.                     setebcdic();
  1478.                     break;
  1479.                 case TYPE_L:
  1480.                     settenex();
  1481.                     break;
  1482.             }
  1483.             if (cpend) {
  1484.                 char msg[2];
  1485.  
  1486.                 fprintf(cout,"%c%c",IAC,IP);
  1487.                 (void) fflush(cout); 
  1488.                 *msg = IAC;
  1489.                 *(msg+1) = DM;
  1490.                 if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1491.                     perror("abort");
  1492.                 fprintf(cout,"ABOR\r\n");
  1493.                 (void) fflush(cout);
  1494.                 FD_ZERO(&mask);
  1495.                 FD_SET(fileno(cin), &mask);
  1496.                 if ((nfnd = empty(&mask,10)) <= 0) {
  1497.                     if (nfnd < 0) {
  1498.                         perror("abort");
  1499.                     }
  1500.                     if (ptabflg)
  1501.                         code = -1;
  1502.                     lostpeer();
  1503.                 }
  1504.                 (void) getreply(0);
  1505.                 (void) getreply(0);
  1506.             }
  1507.             pswitch(1);
  1508.             if (ptabflg)
  1509.                 code = -1;
  1510.             (void) signal(SIGINT, oldintr);
  1511.             return;
  1512.         }
  1513.     }
  1514.     if (cpend) {
  1515.         char msg[2];
  1516.  
  1517.         fprintf(cout,"%c%c",IAC,IP);
  1518.         (void) fflush(cout); 
  1519.         *msg = IAC;
  1520.         *(msg+1) = DM;
  1521.         if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1522.             perror("abort");
  1523.         fprintf(cout,"ABOR\r\n");
  1524.         (void) fflush(cout);
  1525.         FD_ZERO(&mask);
  1526.         FD_SET(fileno(cin), &mask);
  1527.         if ((nfnd = empty(&mask,10)) <= 0) {
  1528.             if (nfnd < 0) {
  1529.                 perror("abort");
  1530.             }
  1531.             if (ptabflg)
  1532.                 code = -1;
  1533.             lostpeer();
  1534.         }
  1535.         (void) getreply(0);
  1536.         (void) getreply(0);
  1537.     }
  1538.     pswitch(!proxy);
  1539.     if (cpend) {
  1540.         FD_ZERO(&mask);
  1541.         FD_SET(fileno(cin), &mask);
  1542.         if ((nfnd = empty(&mask,10)) <= 0) {
  1543.             if (nfnd < 0) {
  1544.                 perror("abort");
  1545.             }
  1546.             if (ptabflg)
  1547.                 code = -1;
  1548.             lostpeer();
  1549.         }
  1550.         (void) getreply(0);
  1551.         (void) getreply(0);
  1552.     }
  1553.     if (proxy)
  1554.         pswitch(0);
  1555.     switch (oldtype) {
  1556.         case 0:
  1557.             break;
  1558.         case TYPE_A:
  1559.             setascii();
  1560.             break;
  1561.         case TYPE_I:
  1562.             setbinary();
  1563.             break;
  1564.         case TYPE_E:
  1565.             setebcdic();
  1566.             break;
  1567.         case TYPE_L:
  1568.             settenex();
  1569.             break;
  1570.     }
  1571.     pswitch(1);
  1572.     if (ptabflg)
  1573.         code = -1;
  1574.     (void) signal(SIGINT, oldintr);
  1575. }
  1576.  
  1577. reset()
  1578. {
  1579.     struct fd_set mask;
  1580.     int nfnd = 1;
  1581.  
  1582.     FD_ZERO(&mask);
  1583.     while (nfnd > 0) {
  1584.         FD_SET(fileno(cin), &mask);
  1585.         if ((nfnd = empty(&mask,0)) < 0) {
  1586.             perror("reset");
  1587.             code = -1;
  1588.             lostpeer();
  1589.         }
  1590.         else if (nfnd) {
  1591.             (void) getreply(0);
  1592.         }
  1593.     }
  1594. }
  1595.  
  1596. char *
  1597. gunique(local)
  1598.     char *local;
  1599. {
  1600.     static char new[MAXPATHLEN];
  1601.     char *cp = rindex(local, '/');
  1602.     int d, count=0;
  1603.     char ext = '1';
  1604.  
  1605.     if (cp)
  1606.         *cp = '\0';
  1607.     d = access(cp ? local : ".", 2);
  1608.     if (cp)
  1609.         *cp = '/';
  1610.     if (d < 0) {
  1611.         perror(local);
  1612.         return((char *) 0);
  1613.     }
  1614.     (void) strcpy(new, local);
  1615.     cp = new + strlen(new);
  1616.     *cp++ = '.';
  1617.     while (!d) {
  1618.         if (++count == 100) {
  1619.             printf("runique: can't find unique file name.\n");
  1620.             return((char *) 0);
  1621.         }
  1622.         *cp++ = ext;
  1623.         *cp = '\0';
  1624.         if (ext == '9')
  1625.             ext = '0';
  1626.         else
  1627.             ext++;
  1628.         if ((d = access(new, 0)) < 0)
  1629.             break;
  1630.         if (ext != '0')
  1631.             cp--;
  1632.         else if (*(cp - 2) == '.')
  1633.             *(cp - 1) = '1';
  1634.         else {
  1635.             *(cp - 2) = *(cp - 2) + 1;
  1636.             cp--;
  1637.         }
  1638.     }
  1639.     return(new);
  1640. }
  1641.